using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using ISXWoW;
using LavishVMAPI;
using InnerSpaceAPI;
using System.IO;
using System.Xml;

namespace ISXUGAuction
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        string STATE = "OFF";

        #region Mailbox Handling

        /* ================= RetrieveMail ==============
         * Will grab all items and money from your mail.
         * ============================================= */

        private void RetrieveMail()
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            UGMailCmd mailcmd = new UGMailCmd();
            mailcmd.CheckMail();
            int numOfItems = mailcmd.GetMailAmmount();
            while (numOfItems > 0 && !BagFull())
            {
                List<UGMail> mailList = mailcmd.RetrieveMailList();

                for (int i = 0; i < mailList.Count; i++)
                {
                    int index = mailList[i].index;
                    string sender = mailList[i].sender;
                    bool wasRead = mailList[i].wasRead;
                    bool hasItem = mailList[i].wasReturned;
                    int money = mailList[i].money;
                    if (money != 0)
                        mailcmd.TakeInboxMoney(i);
                    else if (hasItem)
                        mailcmd.TakeInboxItem(i);
                    else if (wasRead && money == 0 && !hasItem)
                        mailcmd.DeleteInboxItem(i);
                }

                numOfItems = mailcmd.GetMailAmmount();
            }
        }

        #endregion

        #region Auction House Upgrade Handling


        private void CheckForUpgrades(string type)
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            //Frame.Lock();
            int maxLevel = isxwow.Me.Level;
            int minLevel = maxLevel - 4;
            //Frame.Unlock();
            List<InventoryItem> gearList = GetMyGearList();
        }

        private List<InventoryItem> GetMyGearList()
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            List<InventoryItem> returnList = new List<InventoryItem>();
            for (int i = 1; i < 18; i++) // loop from 1 to 18 to check important gear
            {
                string link = GetInventoryItemLink(i);
                if (link != "") // make sure we have an item in that slot
                {
                    string itemName = GetWoWItemName(link);
                    int itemQualityNum = GetWoWItemQuality(link);
                    int itemLevel = GetWoWItemLevel(link);
                    int itemMinLevel = GetWoWItemMinLevel(link);
                    string itemType = GetWoWItemType(link);
                    string itemSubtype = GetWoWItemSubType(link);
                    int itemStackCount = GetWoWItemStackCount(link);
                    string itemEquipLocation = GetWoWItemEquipLoc(link);
                    InventoryItem temp = new InventoryItem(itemName, link, itemQualityNum, itemLevel, itemMinLevel,
                        itemType, itemSubtype, itemStackCount, itemEquipLocation);
                    returnList.Add(temp);
                }
            }

            return returnList;
        }

        private string GetInventoryItemLink(int slotID)
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            string returnstring;

            returnstring = isxwow.WoWScript<string>("GetInventoryItemLink(\"player\"," + slotID + ")");
            return returnstring;
        }

        #endregion

        #region Auction House Search For Best Deal

        private void SearchForBestDeal(string item)
        {
            Auction ah = new Auction();
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();

            List<AuctionItem> itemList = new List<AuctionItem>();

            ah.Query(item, 0);
            int pages = ah.GetNumberOfPages();
            if (pages != 0)
            {
                itemList.AddRange(ah.GetAuctionList());
                if (pages > 1)
                {
                    for (int i = 1; i < pages; i++)
                    {
                        ah.Query(item, i);
                        itemList.AddRange(ah.GetAuctionList());
                    }
                }
                for (int i = 0; i < itemList.Count; i++)
                {
                    if (itemList[i].name != item)
                        itemList.RemoveAt(i);
                }
                AuctionItem cheapestItem = CheapestItem(itemList);
                int cheapestBO = cheapestItem.buyoutPrice;
            }
        }

        #endregion

        #region Auction House Sell Handling

        /// <summary>
        /// ============================== SellItems ===========================================
        /// This big momma routine puts all the little guys together to actually iterate through
        /// each item in your bag and put it up on the auction house while undercutting the
        /// competiton.
        /// ====================================================================================
        /// </summary>
        private void SellItems()
        {
            // Step 1 - Declare Startup Variables/Objects
            Auction ah = new Auction();
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            List<WoWItem> backpackList = GetBackpackList(); // The list of items in our backpack
            List<BagItem> sellItems = new List<BagItem>(); // The list of the items to sell in our backpack, WITH prices

            // Step 2 - Select an item to check from our backpack.
            for (int i = 0; i < backpackList.Count; i++)
            {
                string backpackItemName = backpackList[i].Name;
                if (!ItemAlreadyScanned(sellItems, backpackItemName)) // make sure we dont scan the AH for the same item twice
                {
                    int stackCount = backpackList[i].GetItem().StackCount; // number of items in the item stack
                    int sellPrice = (stackCount * FindSellPrice(backpackItemName)); // the sell price with the items in the stack figured in
                    if (sellPrice != 0) // if we found a price for it
                    {
                        // Step 3 - Add all eligble items to sell to a list
                        BagItem temp = new BagItem(backpackItemName, i, sellPrice, true, "null"); // **SETS canSell TO TRUE FOR NOW, DEBUGGING***
                        sellItems.Add(temp);
                    }
                }
                else // dont scan the AH for it but still give it a sellItem data entry so that it sells it
                {
                    int price = RetrieveScannedItemPrice(sellItems, backpackItemName);
                    BagItem temp = new BagItem(backpackItemName, i, price, true, "null"); // also for above.. the null is for a feature yet to be implemented
                    sellItems.Add(temp);
                }
            }

            // ISXUGAuction Additional Step - Mark items as cannot be sold
            foreach (BagItem item in sellItems)
            {
                string itemName = item.name;
                if (ItemCantBeSold(itemName))
                    item.canSell = false;
            }

            foreach (BagItem item in sellItems)
            {
                if (item.canSell)
                {
                    // Step 4 - Pickup the item and put it into the Auction House slot
                    backpackList[item.bagSlotID].PickUp();
                    int oldPrice = item.price;
                    isxwow.WoWScript("ClickAuctionSellItemButton()");
                    // Step 5 - Calculate the price and post it with undercutting percent figured in
                    double undercutPct = Convert.ToDouble(undercutPctBox.Text) * .01;
                    int undercut = (int)(oldPrice * undercutPct);
                    int boPrice = oldPrice - undercut;
                    double startPricePct = .15; // your items bidding price is 20% cheaper
                    int lessStartprice = (int)(startPricePct * boPrice);
                    int startPrice = boPrice - lessStartprice;
                    int auctionTime = 8 * 60; // default time is 8h, check if we need another time
                    if (twoHBox.Checked)
                        auctionTime = 2 * 60;
                    if (eightHBox.Checked)
                        auctionTime = 8 * 60;
                    if (twofourHBox.Checked)
                        auctionTime = 24 * 60;
                    // Step 6 - Pray that it didn't just sell all your shit for free!
                    ah.StartAuction(startPrice, boPrice, auctionTime);
                }
            }
            // Now... latest addition... do we want to sell items even if we can't get the data
            // on their pricing from the auction house based on a guess of how much it's worth?
            if (sellUnfoundBox.Checked)
            {
                Thread.Sleep(5000);
                SellFromPredeterminedPrice();
            }
        }

        private bool ItemCantBeSold(string itemName)
        {
            foreach (WoWItem item in dontSellList)
            {
                if (itemName == item.Name)
                    return true;
            }
            return false;
        }

        /* ================GetBackpackList===============
         * Will scan your backpack for a list of items.
         * Update: Now will scan all of your bags.
         * ============================================== */

        private List<WoWItem> GetBackpackList()
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();

            List<WoWItem> returnList = new List<WoWItem>();
            WoWContainer container = new WoWContainer(isxwow.Me.Bag(0)); // make bag object of our main bag (index 0 = backpack)
            int filledSlots = container.FilledSlots;
            int maxSlots = container.SlotCount;

            for (int i = 0; i < maxSlots + 1; i++)
            {
                if (container.Item(i).IsValid)
                    returnList.Add(container.Item(i));
            }

            //MessageBox.Show("Number of backpack items: " + returnList.Count.ToString()); /// ***used in debugging***

            return returnList;
        }

        /*================ItemAlreadyScanned======================
         * For use in the SellItems() function, will check to see if
         * you scanned for a certain item already, to prevent double
         * searches.
         * =========================================================*/
        private bool ItemAlreadyScanned(List<BagItem> sellList, string itemName)
        {
            int length = sellList.Count;
            for (int i = 0; i < length; i++)
            {
                if (sellList[i].name == itemName)
                    return true;
            }
            return false;
        }

        /*==================RetrieveScannedItemPrice====================
         * This will return the price of an item already scanned for you
         * so that you dont have to check repeat items price over and 
         * over
         * ============================================================= */

        private int RetrieveScannedItemPrice(List<BagItem> sellList, string itemName)
        {
            int length = sellList.Count;
            int returnPrice = 000000;
            for (int i = 0; i < length; i++)
            {
                if (sellList[i].name == itemName)
                    return sellList[i].price;
            }
            return returnPrice;
        }

        /* ================= FindSellPrice =================
         * Will determine how much you should sell (item) for
         * while undercutting the rest.
         * Note: The returned price is PER ITEM.
         * ex) 1 Light Leather = 1s *RETURNED*
         *    20 Light Leahter = 20s (not returned)
         * ================================================= */

        private int FindSellPrice(string itemName)
        {
            Auction ah = new Auction();
            int returnPrice;
            List<AuctionItem> auctionList = new List<AuctionItem>();

            // Step 1 - Gather information about the query
            ah.Query(itemName, 0);
            int pagesToSearch = ah.GetNumberOfPages();
            // Step 2 - Get the first page of the query
            if (pagesToSearch != 0)
            {
                auctionList.AddRange(ah.GetAuctionList());
                // Step 3 - Get any subsequent pages to of the query
                if (pagesToSearch > 1)
                {
                    for (int i = 1; i < pagesToSearch; i++)
                    {
                        ah.Query(itemName, i);
                        auctionList.AddRange(ah.GetAuctionList());
                    }
                }
                // Step 3.5 - (This add in checks to make sure that the items on the list you search
                //             is for the item that you really want, instead of similiarly named items.)
                for (int q = 0; q < auctionList.Count; q++)
                {
                    if (auctionList[q].name != itemName)
                        auctionList.RemoveAt(q);
                }
                // Step 4 - Find the price of the cheapest item (per Item not per Stack)
                AuctionItem cheapestItem = CheapestItem(auctionList);
                int cheapestItemBO = cheapestItem.buyoutPrice;
                if (cheapestItemBO == 0) // Once again, to prevent those pesky "Divide by 0" errors
                { return 0; }
                int cheapestItemCount = cheapestItem.count;
                int pricePerItem = (int)(cheapestItemBO / cheapestItemCount);

                returnPrice = pricePerItem;
            }
            else
            {
                returnPrice = 0;
            }

            return returnPrice;
        }

        /// <summary>
        /// ============================ CheapestItem ==========================
        /// CheapestItem takes a list of AuctionItems and will search through
        /// them and find the cheapest one. It find the cheapest individual item
        /// not the cheapest stack of them, so it really finds the best deal.
        /// ====================================================================
        /// </summary>
        /// <param name="auctionList">List of current auctions</param>
        /// <returns>The item that is cheapest.</returns>

        private AuctionItem CheapestItem(List<AuctionItem> auctionList)
        {
            // objects
            AuctionItem returnItem = new AuctionItem("", 0, 0, 0, 0, 0, 0, 0, "");
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            Auction ah = new Auction();
            // variables
            int cheapestItemCost = 99999999;
            int auctionListLength = auctionList.Count;
            //MessageBox.Show("Auction List Length: " + auctionListLength.ToString()); // ***Used in DEBUGGING***

            for (int i = 0; i < auctionListLength; i++)
            {
                int itemCount = auctionList[i].count;
                if (itemCount == 0) // to prevent "Divide by 0" errors
                { return returnItem; }
                int itemBO = auctionList[i].buyoutPrice;
                int pricePerItem = (int)(itemBO / itemCount);

                if (pricePerItem < cheapestItemCost && itemBO != 0) // if an item is cheaper and the BO isnt 0
                {
                    cheapestItemCost = pricePerItem;
                    returnItem = auctionList[i];
                }
            }

            return returnItem;
        }

        #endregion

        #region Scan And Record Functions

        /* ============ ScanAndRecord ============
         * Will scan through all the pages and
         * record the pricing for all of the items
         * that it finds. Then it will record the
         * Auction House data to an XML file.
         * ======================================= */

        private void ScanAndRecord()
        {
            Auction ah = new Auction();
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();

            int pagesToCount = 1; // pages to count till (testing is 3)
            List<AuctionItem> auctionList = new List<AuctionItem>(); // list of items

            // Step 1 - Gather the list of Auction Items
            for (int i = 0; i < pagesToCount; i++)
            {
                ah.Query("", i); // query the page were on
                auctionList.AddRange(ah.GetAuctionList()); // add the items to the list
            }

            CheckForXMLFile("AuctionItems.xml"); // check that our XML file exists (if not make it)
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load("AuctionItems.xml");

            // Step 2 - Scan through the auction house items.
            foreach (AuctionItem item in auctionList)
            {
                string itemName = item.name;
                string itemOwner = item.owner;
                int count = item.count;
                int minBid = (int)item.minBid / count;
                int buyOut = (int)item.buyoutPrice / count;
                int itemLvl = item.level;

                // Step 3a - If the item isn't in the data already, make it.
                if (!DoesItemXMLExist(itemName))
                {
                    XmlElement ahItem = xmlDoc.CreateElement("AuctionItem");
                    XmlAttribute ahItemName = xmlDoc.CreateAttribute("ItemName");
                    ahItem.Value = itemName;
                    ahItem.SetAttributeNode(ahItemName);

                    XmlElement XMLMinimumBid = xmlDoc.CreateElement("MinimumBid");
                    XMLMinimumBid.InnerText = minBid.ToString();
                    ahItem.AppendChild(XMLMinimumBid);

                    XmlElement XMLBuyOutPrice = xmlDoc.CreateElement("Buyout");
                    XMLBuyOutPrice.InnerText = buyOut.ToString();
                    ahItem.AppendChild(XMLBuyOutPrice);

                    xmlDoc.DocumentElement.InsertAfter(ahItem, xmlDoc.DocumentElement.LastChild);
                    xmlDoc.Save("AuctionItems.xml");
                }
                // Step 3b - If the item already exists, just add the price data.
                else
                {
                    XmlNodeList xmlNode = xmlDoc.GetElementsByTagName("AuctionItem");
                    foreach (XmlNode x in xmlNode)
                    {
                        XmlAttributeCollection attributes = x.Attributes;
                        if (attributes[0].Value == itemName)
                        {
                            XmlElement XMLMinimumBid = xmlDoc.CreateElement("MinimumBid");
                            XMLMinimumBid.InnerText = minBid.ToString();
                            x.AppendChild(XMLMinimumBid);

                            XmlElement XMLBuyOutPrice = xmlDoc.CreateElement("Buyout");
                            XMLBuyOutPrice.InnerText = buyOut.ToString();
                            x.AppendChild(XMLBuyOutPrice);
                            xmlDoc.Save("AuctionItems.xml");
                        }
                    }
                }
            }
        }

        private bool DoesItemXMLExist(string itemName)
        {
            CheckForXMLFile("AuctionItems.xml");
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load("AuctionItems.xml");
            XmlNodeList xmlNode = xmlDoc.GetElementsByTagName("AuctionItem");
            foreach (XmlNode x in xmlNode)
            {
                XmlAttributeCollection atr = x.Attributes;
                if (atr[0].Value == itemName)
                    return true;
            }
            return false;
        }

        private void CheckForXMLFile(string name)
        {
            XmlDocument xmlDoc = new XmlDocument();
            try
            {
                xmlDoc.Load(name);
            }
            catch (System.IO.FileNotFoundException)
            {
                XmlTextWriter xmlWriter = new XmlTextWriter(name, System.Text.Encoding.UTF8);
                xmlWriter.Formatting = Formatting.Indented;
                xmlWriter.WriteProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
                xmlWriter.WriteStartElement("ISXAutioneer");
                xmlWriter.WriteEndElement();
                xmlWriter.Close();
                xmlDoc.Load(name);
            }
        }

        #endregion

        #region Inventory Item Handling

        private bool BagFull()
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            int totalSlots = 0;
            int fullSlots = 0;
            for (int i = 0; i < NumOfBags(); i++)
            {
                WoWContainer container = new WoWContainer(isxwow.Me.Bag(i));
                totalSlots += container.SlotCount;
                fullSlots += container.FilledSlots;
            }

            if (fullSlots == totalSlots)
                return true;

            return false;
        }

        private int NumOfBags()
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            int rBags = 0;
            for (int i = 0; i < 4; i++)
            {
                if (isxwow.Me.Bag(i).IsValid)
                    rBags++;
            }
            return rBags;
        }

        /* ===========SellFromGuessedprice===========
         * This will sell your (armor/weapons) where
         * current prices weren't found on the AH
         * based on an ammount predetermined by the 
         * type and level of the item.
         * 
         * ***UPDATE***
         * This was never truely implemented... I got it half functional before I just said forget it.
         * When I tested it, I had 4 items in my bag lined up - the first one and the last one were put
         * up for auction for 0c (Didn't even know it was possible), the two middle ones were put up
         * for the ammount that I have listed the should have been. The problem may be with this code
         * or just the system of how I worked things, but I decided I don't want to try to figure it out.
         * 
         * ***UPDATE 2***
         * I finished working on this and it works like a charm! This function never had anything wrong
         * wih it in the first place, the problems mentioned above were something else that is now fixed.
         * ========================================== */

        private void SellFromPredeterminedPrice()
        {
            Auction ah = new Auction();
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();

            // Step 1 - Get the unsold item list.
            List<WoWItem> unsoldList = GetBackpackList();
            // Step 2 - Make the BagItem list out of our unsold item list
            for (int i = 0; i < unsoldList.Count; i++)
            {
                string itemName = unsoldList[i].Name;
                int bagSlot = unsoldList[i].Slot;
                string link = "notworking";
                // Step 3 - Determine what slot the item is in, get the link
                WoWContainer thebag = new WoWContainer(isxwow.Me.Bag(0));
                int maxSlots = thebag.SlotCount;
                //  && GetWoWItemName(GetWoWBagItemLink(0, q)) == itemName
                for (int q = 0; q < maxSlots; q++)
                {
                    if (thebag.Item(q).IsValid)
                    {
                        link = GetWoWBagItemLink(0, q);
                    }
                }

                string quality = GetWoWItemQualityString(link);
                string type = GetWoWItemType(link);
                int level = GetWoWItemMinLevel(link);
                int price = 000000;
                // Step 4 - Set prices for Armor and Weapons that aren't on the AH right now.
                if (type == "Armor")
                {
                    if (level < 10 && quality != "Rare" && quality != "Epic")
                        price = 2000; //20s
                    if (level >= 10 && level < 20 && quality != "Rare" && quality != "Epic")
                        price = 5000; // 50s
                    if (level >= 20 && level < 30 && quality != "Rare" && quality != "Epic")
                        price = 10000; // 1g
                    if (level >= 30 && level < 40 && quality != "Rare" && quality != "Epic")
                        price = 15000; // 1g 50s
                    if (level >= 40 && level < 50 && quality != "Rare" && quality != "Epic")
                        price = 20000; // 2g
                    if (level >= 50 && level < 60 && quality != "Rare" && quality != "Epic")
                        price = 40000; // 4g
                    if (level >= 60 && quality != "Rare" && quality != "Epic")
                        price = 50000; // 5g
                }
                if (type == "Weapon")
                {
                    if (level < 10 && quality != "Rare" && quality != "Epic")
                        price = 4000; // 40s
                    if (level >= 10 && level < 20 && quality != "Rare" && quality != "Epic")
                        price = 7500; // 75s
                    if (level >= 20 && level < 30 && quality != "Rare" && quality != "Epic")
                        price = 12500; // 1g 25s
                    if (level >= 30 && level < 40 && quality != "Rare" && quality != "Epic")
                        price = 30000; // 3g
                    if (level >= 40 && level < 50 && quality != "Rare" && quality != "Epic")
                        price = 50000; // 5g
                    if (level >= 50 && level < 60 && quality != "Rare" && quality != "Epic")
                        price = 50000; // 5g
                    if (level >= 60 && quality != "Rare" && quality != "Epic")
                        price = 80000; // 8g
                }

                // Step 5 - Sell the item.
                int boPrice = price;
                double pctMinBid = .05;
                int startPrice = (int)(boPrice * pctMinBid);
                int auctionTime = 8 * 60; // 8 hrs
                if (boPrice != 0)
                {
                    unsoldList[i].PickUp();
                    isxwow.WoWScript("ClickAuctionSellItemButton()");
                    ah.StartAuction(startPrice, boPrice, auctionTime);
                }
                else
                {
                }
            }
        }
        #endregion

        #region Item Information Retrieval

        private string GetWoWBagItemLink(int bagID, int index)
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();

            return isxwow.WoWScript<string>("GetContainerItemLink(" + bagID + "," + index + ")");
        }

        private string GetWoWItemType(string link)
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();

            return isxwow.WoWScript<string>("GetItemInfo(\"" + link + "\")", 6);
        }

        private string GetWoWItemName(string link)
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();

            return isxwow.WoWScript<string>("GetItemInfo(\"" + link + "\")", 1);
        }

        private int GetWoWItemLevel(string link)
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();

            return isxwow.WoWScript<int>("GetItemInfo(\"" + link + "\")", 4);
        }

        private int GetWoWItemMinLevel(string link)
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();

            return isxwow.WoWScript<int>("GetItemInfo(\"" + link + "\")", 5);
        }

        private string GetWoWItemSubType(string link)
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            return isxwow.WoWScript<string>("GetItemInfo(\"" + link + "\")", 7);
        }

        private int GetWoWItemStackCount(string link)
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            return isxwow.WoWScript<int>("GetItemInfo(\"" + link + "\")", 8);
        }

        private string GetWoWItemEquipLoc(string link)
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            return isxwow.WoWScript<string>("GetItemInfo(\"" + link + "\")", 9);
        }

        private int GetWoWItemQuality(string link)
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            return isxwow.WoWScript<int>("GetItemInfo(\"" + link + "\")", 3);
        }

        private string GetWoWItemQualityString(string link)
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            int quality = isxwow.WoWScript<int>("GetItemInfo(\"" + link + "\")", 3);
            if (quality == 0)
                return "Poor";
            if (quality == 1)
                return "Common";
            if (quality == 2)
                return "Uncommon";
            if (quality == 3)
                return "Rare";
            if (quality == 4)
                return "Epic";
            if (quality == 5)
                return "Legendary";
            if (quality == 6)
                return "Artifact";
            return "Failed";
        }

        #endregion

        #region Movement and Interaction

        /* ================== MoveToMidPoint =================
         * In order to get from the Auction House to the Mail-
         * box, you need to go through some sort of mid point.
         * This will run you to this mid point, based off of a
         * pre-determined point... in between them.
         * =================================================== */

        private void MoveToMidPoint()
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            WoWMovement movement = new WoWMovement();

            double pX = 1667.549072; // insert middle point X,Y here
            double pY = -4429.826172; //
            double meX = isxwow.Me.X;
            double meY = isxwow.Me.Y;

            // Do some crazy math to determine our distance
            double dist = Math.Sqrt(Math.Pow(pX - meX, 2) + Math.Pow(pY - meY, 2));

            while (dist > 2)
            {
                meX = isxwow.Me.X;
                meY = isxwow.Me.Y;

                dist = Math.Sqrt(Math.Pow(pX - meX, 2) + Math.Pow(pY - meY, 2));

                isxwow.Face(pX, pY); // face our point
                movement.Go(MovementDirection.Forward); // move forward
            }
            movement.Stop();
        }

        private void MoveToClosestMailbox()
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            WoWMovement movement = new WoWMovement();
            GuidList guidList = new GuidList();
            guidList.Search("-noself");
            for (int i = 0; i < guidList.Count; i++)
            {
                if (guidList.Object(Convert.ToUInt32(i)).Name == "Mailbox")
                {
                    while (guidList.Object(Convert.ToUInt32(i)).GetDynamicGameObject().Distance > 4)
                    {
                        guidList.Object(Convert.ToUInt32(i)).GetDynamicGameObject().Face();
                        movement.Go(MovementDirection.Forward);
                    }
                    LavishScriptAPI.LavishScript.ExecuteCommand(String.Format("move -stop"));
                    guidList.Object(Convert.ToUInt32(i)).GetDynamicGameObject().Use();
                }
            }
        }

        private void MoveToClosestAuctioneerTwo()
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            WoWMovement movement = new WoWMovement();
            GuidList guidList = new GuidList();
            guidList.Search("-noself");
            for (uint i = 0; i < guidList.Count; i++)
            {
                if (guidList.Object(i).Name.Trim() != "")
                {
                    if (guidList.Object(i).GetUnit().IsAuctioneer)
                    {
                        while (guidList.Object(i).GetUnit().Distance > 5)
                        {
                            guidList.Object(i).GetUnit().Face();
                            movement.Go(MovementDirection.Forward);

                        }
                        LavishScriptAPI.LavishScript.ExecuteCommand(String.Format("move -stop"));
                        guidList.Object(i).GetUnit().Use();
                        break;
                    }
                }
            }
        }

        private void MoveToClosestAuctioneer()
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            WoWMovement movement = new WoWMovement();
            GuidList guidList = new GuidList();
            guidList.Search("-noself");
            string name = "";
            double distance = 99999999;
            for (int i = 0; i < guidList.Count; i++)
            {
                if (guidList.Object(Convert.ToUInt32(i)).Name.Trim() != "")
                {
                    if (guidList.Object(Convert.ToUInt32(i)).GetUnit().IsAuctioneer)
                        if (guidList.Object(Convert.ToUInt32(i)).GetUnit().Distance < distance)
                        {
                            name = guidList.Object(Convert.ToUInt32(i)).GetUnit().Name;
                            distance = guidList.Object(Convert.ToUInt32(i)).GetUnit().Distance;
                        }
                }
            }
            for (int i = 0; i < guidList.Count; i++)
            {
                if (guidList.Object(Convert.ToUInt32(i)).GetUnit().Name == name)
                {
                    while (guidList.Object(Convert.ToUInt32(i)).GetUnit().Distance > 5)
                    {
                        guidList.Object(Convert.ToUInt32(i)).GetUnit().Face();
                        movement.Go(MovementDirection.Forward);

                    }
                    LavishScriptAPI.LavishScript.ExecuteCommand(String.Format("move -stop"));
                    guidList.Object(Convert.ToUInt32(i)).GetUnit().Use();
                }
            }
        }

        #endregion

        /* ============ WriteLog() ==========
         * Will make a log of all the items
         * sold, and money looted. */

        private void WriteLog()
        {
            int day = DateTime.Now.Day;
            int month = DateTime.Now.Month;
            int year = DateTime.Now.Year;
            int hour = DateTime.Now.Hour;
            int minute = DateTime.Now.Minute;
            string timeDate = (month.ToString() + "-" + day.ToString() + "-" + year.ToString() + " " + hour.ToString() + "-" + minute.ToString());
            string logFileName = ("ISXAuctioneerLog" + timeDate + ".txt");
            string formtimedate = DateTime.Now.ToString();
            FileInfo t = new FileInfo(logFileName);
            StreamWriter tw = t.CreateText();
            tw.WriteLine("  ISXAuctioneer Log for " + formtimedate);
            tw.WriteLine(tw.NewLine);
            tw.WriteLine("====Accurately Priced Items Sold====");
            tw.WriteLine(tw.NewLine);
            tw.WriteLine("====Best Guess Priced Items Sold====");
            tw.WriteLine(tw.NewLine);
            tw.WriteLine("Money Made from Mail Loot: ");
            tw.WriteLine(tw.NewLine);
            tw.WriteLine("  (Generated by ISXAuctioneer Logger)");
            tw.WriteLine(tw.NewLine);
            tw.Close();
        }

        List<WoWItem> sellList = new List<WoWItem>();
        List<WoWItem> dontSellList = new List<WoWItem>();

        private void button3_Click(object sender, EventArgs e)
        {
            // start
            List<WoWItem> backpackList = GetBackpackList();
            foreach (WoWItem item in backpackList)
            {
                itemsInBag.Items.Add(item.Name);
                sellList.Add(item);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // dont sell
            if (itemsInBag.SelectedIndex > -1)
            {
                string itemName = itemsInBag.Items[itemsInBag.SelectedIndex].ToString();
                itemsNotToSell.Items.Add(itemName);

                for (int i = 0; i < sellList.Count; i++)
                {
                    WoWItem item = sellList[i];
                    if (item.Name == itemName)
                    {
                        sellList.RemoveAt(i);
                        dontSellList.Add(item);
                    }
                }

                itemsInBag.Items.RemoveAt(itemsInBag.SelectedIndex);
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            // sell it
            if (itemsNotToSell.SelectedIndex > -1)
            {
                string itemname = itemsNotToSell.Items[itemsNotToSell.SelectedIndex].ToString();
                itemsInBag.Items.Add(itemname);

                for (int i = 0; i < dontSellList.Count; i++)
                {
                    WoWItem item = dontSellList[i];
                    if (item.Name == itemname)
                    {
                        dontSellList.RemoveAt(i);
                        sellList.Add(item);
                    }
                }

                itemsNotToSell.Items.RemoveAt(itemsNotToSell.SelectedIndex);
            }
        }

        private void button5_Click(object sender, EventArgs e)
        {
            // START
            ParameterizedThreadStart p = new ParameterizedThreadStart(BotLoop);
            Thread t = new Thread(p);
            string[] str = { "STR" };
            runningCheckBox.Checked = true;
            t.Start(str);
        }

        private void BotLoop(object p)
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            UGMailCmd mc = new UGMailCmd();
            bool running = runningCheckBox.Checked;

            while (running)
            {
                running = runningCheckBox.Checked;

                if (STATE == "OFF")
                    STATE = "ON";

                if (STATE == "ON")
                {
                    if (mc.HasMail() && !BagFull())
                        STATE = "GET_MAIL";
                    if (!mc.HasMail() || BagFull())
                        STATE = "AUCTION";
                    if (!mc.HasMail() && !BagFull() && HasItemToSell())
                        STATE = "AUCTION";
                }

                if (STATE == "GET_MAIL")
                {
                    MoveToMidPoint();
                    MoveToClosestMailbox();
                    RetrieveMail();
                    STATE = "AUCTION";
                }

                if (STATE == "AUCTION")
                {
                    MoveToMidPoint();
                    MoveToClosestAuctioneerTwo();
                    SellItems();
                    if (mc.HasMail() && !BagFull())
                        STATE = "GET_MAIL";
                    else
                        STATE = "DONE";
                }

                if (STATE == "DONE")
                {
                    running = false;
                    runningCheckBox.Checked = false;
                    MessageBox.Show("Done!");
                }
            }

            STATE = "OFF";
        }

        private bool HasItemToSell()
        {
            ISXWoW.ISXWoW isxwow = new ISXWoW.ISXWoW();
            int totalSlots = 0;
            int fullSlots = 0;
            List<WoWItem> itemsInBag = new List<WoWItem>();
            for (int i = 0; i < NumOfBags(); i++)
            {
                WoWContainer container = new WoWContainer(isxwow.Me.Bag(i));
                totalSlots += container.SlotCount;
                fullSlots += container.FilledSlots;
                for (int q = 0; q < container.SlotCount; q++)
                {
                    if (container.Item(q).IsValid)
                        itemsInBag.Add(container.Item(i));
                }
            }
            int itemsToBeSold = itemsInBag.Count;
            if (fullSlots > 0)
            {
                foreach (WoWItem item in itemsInBag)
                {
                    string itemName = item.Name;
                    if (ItemCantBeSold(itemName))
                        itemsToBeSold--;
                }
            }

            if (itemsToBeSold > 0)
                return true;

            return false;
        }
    }
}